---
--类名: AchievementManager.lua
--创建日期: 2018-4-16
--创建人: 宋建邦
--功能描述: 
--修改内容:
--修改日期:   
--修改人:      
--修改备注: 
--

local AchievementManager = class("AchievementManager")

function AchievementManager:ctor()
    self.shopId = 72051

    self.eventHandler = UD:onChanged("achievement_task", handler(self, self.taskUpdate))

    -- self.servergoods = {}
    self.statistics = {}
    self.newAch = {}
    self:getTypeTree()
    self.achPointsDirty = true
end

AchievementManager.tabAchievement = 1
AchievementManager.tabShop = 2

local function AchievementTask(d)
    local ret = {}
    setmetatable(ret, {__index=d})

    function ret:isTaken()
        return self.state == 1
    end
    
    function ret:isFinished()
        return self.state == 2
    end
    
    function ret:isRewarded()
        return self.state == 3
    end

    function ret:getDefaultProgress()
        if self.taskProgress then
            return self.taskProgress[1]
        end
        return nil
    end

    return ret
end

function AchievementManager:init()
end

AchievementManager.AchDataChange = "achievement.data.change"
function AchievementManager:reqAchievements()
    app.session:request("pb_task.C2S_GetAchievementInfo",{},function(msg)
        self.achTasks = {}

        if msg.taskDatas then
            for i, v in ipairs(msg.taskDatas) do
                self.achTasks[v.id] = AchievementTask(v)
            end
        end

        if self.achPointsDirty then
            self.achPointsDirty = false
            self.typeTree = nil
            self.typeContents = nil
        end

        self:getTypeTree()
        EM:notify(AchievementManager.AchDataChange)
    end)
end

function AchievementManager:getTaskById(id)
    if self.achTasks then
        return self.achTasks[id]
    end
end

function AchievementManager:taskUpdate(tasks)
    if tasks and #tasks > 0 then
        self.achTaskIds = self.achTaskIds or {}
        local task
        for i, v in ipairs(tasks) do
            task = AchievementTask(v)
            if task and self.achTaskIds[task.id] then
                if task:isFinished() then
                elseif task:isRewarded() then
                    UD.badge:setNum(Constant.FUNC_TYPE_CJ, 1)
                    app:dispatchCustomEvent("EVENT_GET_ACHIEVEMENT",{task = task, achID = self.achTaskIds[task.id].achID}) 
                end

                if self.achTasks then
                    self.achTasks[task.id] = task
                end
            end
        end

        self.achPointsDirty = true
    end
end

function AchievementManager:getTypeTree()
    if self.typeTree then
        return self.typeTree
    end

    local types = GD:getAchievementTypes()
    
    self.typeTree = {entries={},children={}}
    local e = self.typeTree.entries
    local c = self.typeTree.children
    
    for index, entry in ipairs(types) do
        local tv = entry:getValues()
        tv.ID = tonumber(tv.ID)
        tv.order = tonumber(tv.order)
        tv.belong = tonumber(tv.belong)
        tv.children = {}
        tv.sumPoint = 0

        if tv.belong == 0 then
            self.typeTree.children[#self.typeTree.children + 1] = tv
        end 

        self.typeTree.entries[tv.ID] = tv
    end

    for id, entry in pairs(self.typeTree.entries) do
        if entry.belong ~= 0 then
            table.insert(e[entry.belong].children, entry)
        end
    end

    self:getAchList()

    local function calcTotalPoint(e)
        if #e.children > 0 then
            local totalPoint = 0
            local totalCurPoint = 0
            for _, v in ipairs(e.children) do
                local t, c = calcTotalPoint(v)
                totalPoint = totalPoint + t 
                totalCurPoint = totalCurPoint + c 
            end
            e.sumPoint = totalPoint
            e.sumCurPoint = totalCurPoint
            return totalPoint, totalCurPoint
        else
            if self.typeContents[e.ID] then
                return self.typeContents[e.ID].sumPoint, self.typeContents[e.ID].sumCurPoint
            else 
                return 0, 0
            end
        end
    end

    self.totalPoint, self.totalCurPoint = calcTotalPoint(self.typeTree)

    -- print("total point:", self.totalPoint)

    local function sortTypes(t)
        table.sort(t, function(a, b)
            return a.order < b.order
        end)
    end

    sortTypes(self.typeTree.children)
    
    for k, v in pairs(self.typeTree.children) do 
        sortTypes(v.children)
        for ck, cv in pairs(v.children) do 
            sortTypes(cv.children)
        end
    end
    return self.typeTree
end 

function AchievementManager:getRootType(tID)
    local p = self.typeTree.entries[tID]
    while(p.belong ~= 0)
    do
        p = self.typeTree.entries[p.belong]
    end
    return p.ID
end

function AchievementManager:getSubType(tID)
    return self.typeTree.entries[tID].belong
end

function AchievementManager:isAchievementFinished(aID)
    self:getAchList()
    local achcfg = self.achMap[aID]
    if achcfg and achcfg.taskID then
        if self:getTaskById(achcfg.taskID) and (self:getTaskById(achcfg.taskID):isFinished() or self:getTaskById(achcfg.taskID):isRewarded()) then
            return true
        end
    end
    return false
end

function AchievementManager:getAchList()
    if self.typeContents then 
        return self.typeContents
    end 

    self.typeContents = {}
    self.achTaskIds = {}
    self.gotAches = {}
    self.achMap = {}

    local achs = GD:getAchievements()
    local tv
    for k, v in pairs(achs) do
        tv = v:getValues()
        if checknumber(tv.class) == 0 or checknumber(tv.class) == UD.player.classID then
            tv.ID = tonumber(tv.ID)
            tv.order = tonumber(tv.order)
            tv.belong = tonumber(tv.belong)
            tv.taskID = tonumber(tv.taskID)
            tv.point = tonumber(tv.point)
            tv.curPoint = 0
            self.achMap[tv.ID] = tv
            
            if self:getTaskById(tv.taskID) and (self:getTaskById(tv.taskID):isFinished() or self:getTaskById(tv.taskID):isRewarded()) then
                tv.ct = self:getTaskById(tv.taskID).completeStamp
                tv.curPoint = tv.point

                if tv then
                    table.insert(self.gotAches, tv)
                end
            end

            self.achTaskIds[tv.taskID] = {achID = tv.ID}

            local alist = self.typeContents[tv.belong] or {sumPoint=0, sumCurPoint=0}
            alist[#alist + 1] = tv
            alist.sumPoint = alist.sumPoint + tv.point
            alist.sumCurPoint = alist.sumCurPoint + tv.curPoint
            self.typeContents[tv.belong] = alist
        end
    end 
    
    table.sort(self.gotAches, function(a, b)
        return checknumber(a.ct) > checknumber(b.ct)
    end)

    --排序
    for k, v in pairs(self.typeContents) do 
        table.sort(v, function(a, b)
            if checknumber(a.ct) == checknumber(b.ct) then
                return a.order < b.order
            else
                return checknumber(a.ct) < checknumber(b.ct)
            end
        end )
    end 

    return self.typeContents
end 

function AchievementManager:getAchievementShopItems()
    local shopConfig = GD:queryShopById(self.shopId)
    self.shopName = shopConfig.name
    self.goodsString = shopConfig.goods
    local goods = string.split(self.goodsString, ";")
    self.goods = {}
    if self.servergoods then
        for _, id in ipairs(goods) do 
            local cfg = GD:queryGoodById(id):getValues()
            local scfg = self.servergoods[checknumber(cfg.ID)]
            if scfg and scfg.leftNum > 0 then
                cfg.itemData = UD:parseRewardToBagItem(cfg.item, "|") -- 持有一份itemData

                local itemId = string.split(cfg.item, "|")
                cfg.itemId = checknumber(itemId[2])
                -- 有可能是装备，这个配置是取不到的
                -- cfg.itemRes = GD:queryItemById(cfg.itemId)
                cfg.buyCount = checknumber(itemId[3])

                table.insert(self.goods, cfg)
            end
        end 
    else
        self:queryGoods()
    end

    return self.goods 
end 

function AchievementManager:getShopName()
    return L(self.shopName)
end

AchievementManager.GoodsChangeEventName = "AchievementGoodsChange"
function AchievementManager:queryGoods()
    local am = self
    app.session:request("pb_query.C2S_QueryGoods",{version = 0,shopId = self.shopId},function(msg)
        am.servergoods = {}
        for i,v in ipairs(msg.goods) do
            am.servergoods[v.id] = v 
        end
        EM:notify(AchievementManager.GoodsChangeEventName)
        app:sendMsg("PrestigeShopModel", "updateShopData", self.shopId, msg.goods)
	end)
end

AchievementManager.StatisticsChangeEventName = "AchievementStatisticsChange"
function AchievementManager:queryStatistics()
    if not self._ids then
        local achs = GD:getAchievementStatistics()
        self._ids = {}
        for k, v in pairs(achs) do
            self._ids[#self._ids + 1] = checknumber(v.ID)
        end
    end

    local am = self
    app.session:request("pb_statistic.C2S_StatisticData",{ids = self._ids},function(msg)
        am.statistics = {}
        for i,v in ipairs(msg.infos) do
            am.statistics[v.id] = v.value
        end
        EM:notify(AchievementManager.StatisticsChangeEventName)
	end)
end

return AchievementManager